#include "irc.h"
#include "modem.h"
#include "gpg.h"

// constants defined globablly for convienience use in threads.
static char* xcowsay = "xcowsay --at=50,50 ";
static char* espeak = "espeak \"";
static char* noerr = "\" 2> /dev/null";

/**
 * listen()
 * Responsible for responding to incoming connection requests
 * and establishing a connection with remote machine.
 */
void listen(config * conf)
{
	printf("WAITING...%d\n",conf->fd);
	while (1)
	{	
		wait_for_signal(conf->fd, "RING", -2);
		printf("INCOMING CONNECTION: SENDING RESPONSE\n");
		send_device(conf->fd,"ATA\r");
		if (wait_for_signal(conf->fd, "CONNECT", -2) == 0)
		{
			printf("CONNECTION ESTABLISHED\n");
			connected(conf);
		}
		else
		{
			printf("CONNECTION TIMED OUT");
			disconnect(conf->fd);
		}
	}
}

/**
 * connect_to()
 * Responsible for dialing and esablishing a connection.
 */
void connect_to(char * number, config * conf)
{
	char to_send[strlen(number)+5];
	strcpy(to_send,"ATDT");
	strncat(to_send, number, strlen(number));
	strncat(to_send, "\r", 1);
	printf("DIALING %s\n", number);
	send_device(conf->fd, to_send);	
	if (wait_for_signal(conf->fd, "CONNECT",-4) == 0)
	{
		printf("CONNECTION ESTABLISHED\n");
		connected(conf);
	}
	else 
	{
		printf("CONNECTION TIMED OUT");
		disconnect(conf->fd);
	}
}

/**
 * connected()
 * responsible for main reading loop and output functionality.
 */
void connected(config *conf)
{
	char message[8000];
	strcpy(message, "GPG ");
	char * buffer = NULL;
	printf("Starting GPG handshake...\n");	
	int bol = 0;
	strcat(message, identity->subkeys->keyid);
	message[strlen(message)] = '\r';	
	send_device(conf->fd, message);
	while (bol == 0)
	{
		if (read_device(conf->fd, &buffer) > 0)
		{
			trim(&buffer);
			printf("%s\n", buffer);
			if (strncmp(buffer,"GPG KEYREQ", strlen("GPG KEYREQ") - 1) == 0)
			{
				printf("KEY REQUESTED FROM OTHER END. TRANSMITTING...");
				get_key(identity, message);
				printf("Sending:\n%s\n", message);
				send_device(conf->fd, "GPG KEYSTART\r");
				message[strlen(message)] = '\r';
				send_device(conf->fd, message);	
				send_device(conf->fd, "GPG KEYEND\r");
			}
			else if (strncmp(buffer, "GPG KEYSTART", strlen("GPG KEYSTART") - 1 == 0))
			{
				printf("RECIEVING KEY...\n");
				free(buffer);
				buffer = NULL;	
				gpgme_data_t key;
				gpgme_data_new(&key);
				do	
				{	
					gpgme_data_write(key, buffer, strlen(buffer));
					if  (read_device(conf->fd, &buffer) > 0)
					{
						trim(&buffer);
						printf("%s", buffer);
					}
				} while (strncmp(buffer, "GPG KEYEND", strlen("GPG KEYEND") - 1) == 0);
				gpgme_op_import(ctx, key);
				gpgme_data_release(key);
				send_device(conf->fd, "GPG KEYOK\r");
			}
			else if (strncmp(buffer, "GPG ", 4) == 0)
			{
				if (gpgme_get_key(ctx, buffer+4,&recipient,1) == GPG_ERR_EOF)
				{
					printf("KEY NOT IN DATABASE. REQUESTING KEY.\n");
					send_device(conf->fd, "GPG KEYREQ\r");	
				}
				else
				{
					send_device(conf->fd, "GPG KEYOK\r");
				}
			}
			if (strcmp(buffer,"GPG KEYOK") == 0)
			{
				bol = 1;
			}
		}
		USLEEP(100);
	}	
	
	
	// alocate a small buffer for our cow :)
	char* cowBuffer = (char*)malloc(sizeof (char) * 2048);
	int carrier = 1;
	while (carrier == 1)
	{
		if (read_device(conf->fd, &buffer) > 0)
		{
			trim(&buffer);
			printf("<Buffer contents>\n%s\n</Buffer contents>\n", buffer);
			
			if (strncmp(buffer,"MSG",3) == 0)
			{
				if (strncmp(buffer+4, "-----BEGIN PGP MESSAGE-----", strlen("-----BEGIN PGP MESSAGE-----") - 1))
				{
					printf("Gpg message detected! Buffering...\n");
					gpgme_data_t buf;
					gpgme_data_new_from_mem(&buf, buffer+4, strlen(buffer+4), 1);
					gpgme_data_seek(buf, 0, SEEK_END);
					while (strncmp(buffer,"-----END PGP MESSAGE-----", strlen("-----END PGP MESSAGE-----")) != 0)
					{
						if (read_device(conf->fd, &buffer) > 0)
						{
							trim(&buffer);
							printf("Writing: %s\n",buffer);
							gpgme_data_write(buf, buffer, strlen(buffer));
						}
					}
					char buffer2[strlen(buffer)];
					//printf("Decrpyting data...");
					decrypt_gpg_dh(buf, buffer2);
					printf("%s: %s\n", conf->nick, buffer2);
				}
			/*	
				strcpy(cowBuffer, buffer2);
				// start two threads for for the cow.
				pthread_t draw;
				pthread_create(&draw, NULL, &cowdraw, cowBuffer);
				pthread_t speak;
				pthread_create(&speak, NULL, &cowspeak, cowBuffer);*/
			}
			// no carrier indicate lost connect, fail out of loop.
			else if (strncmp(buffer,"NO CARRIER", strlen("NO CARRIER")-1) == 0)
			{
				printf("LOST CONNECTION. CARRIER SIGNAL LOST.\n");
				carrier = 0; // "break"
			}
			if (strncmp(buffer, "NICK", strlen("NICK") - 1) == 0)
			{
				memset(conf->nick,0,20);
				strncpy(conf->nick, buffer+5, -1+strlen(buffer+5));
			}
		}
	}
	//free the cowbuffer
	if (cowBuffer != NULL)
		free(cowBuffer);
	cowBuffer = NULL;
}

/**
 * Thread for making the cow actually speak.
 * Depends on the program "espeak"
 */
void* cowspeak(void* message)
{
	char buffer[1024];
	strcpy(buffer, espeak);
	strcat(buffer, (char*)message);
	strcat(buffer, noerr);
	system(buffer);
	return NULL;
}

/**
 * Thread for drawing a cute cow animation
 * Depends on the program "xcowsay"
 */
void* cowdraw(void* message)
{
	char buffer[1024];
	strcpy(buffer, xcowsay);
	strcat(buffer, (char*)message);
	system(buffer);
	return NULL;
}
